【并发】threading & multiprocessing
参考:
- https://www.cnblogs.com/MrZhangLoveLearning/p/5079941.html
- https://zhuanlan.zhihu.com/p/20167077
- https://www.jianshu.com/p/a69dec87e646
- https://docs.python.org/zh-cn/3/library/multiprocessing.html
结论:
- 由于python是一个解释性语言,即在执行时需要CPython编译器(或JPython等),其在为引入全局变量时,构建了GIL(全局锁)。导致python在进行多线程时,由于GIL的存在,本该异步进行的任务,会抢夺一个线程上的全局锁,导致依然一个线程上执行
- 即对I/O密集型任务,采用多线程ok,否则多线程反而起反作用
- python使用多进程可以有效的利用多核CPU
实现
# 进程池实现
from muiltprocessing import Pool
import time
def add(num):
res = 1
for i in range(num):
res += i
print('mut:', time.time.now())
return res
def mut(num):
res = 1
for i in range(num):
res *= i
print('mut:', time.time.now())
return res
pool = Pool(4) # 创建包含4个进程的进程池
pool.apply_async(func=add, 100000) # 添加进程
pool.apply_async(func=mut, 100000) # 添加进程
p.close() # 等任务结束后关闭进程池
# p.terminate() # 立刻关闭进程池
p.join() # 主进程等待所有子进程执行完毕
# 进程添加实现
from muiltprocessing import Process
t1 = Process(task=add, 10000)
t2 = Process(task=mut, 10000) # 创建process对象
t1.start()
t2.start() # 调用process对象生成进程
t1.join()
t2.join() # 等待进程执行完毕,可以通过设置timeout确定任务阻塞时间
# 进程间的通讯通道 -- 队列
## 实质:合理安排不同任务对应的执行进程,目的是保证线程、进程安全
from muiltprocessing import Queue
q = Queue() # 创建任务队列
t1 = Process(task=add, 10000)
t2 = Process(task=mut, 10000) # 创建process对象
t1.start()
t2.start() # 生成进程
print(q.get()) # 获取任务队列的生成结果
t1.join()
t2.join()
# 进程的通讯通道 -- 管道
## 实质
说明:
- 进程池pool无法放在类内进行同步调用,原因是实例方法不能被pickle
- 进程池只能由创建的进程使用,且在交互解释器内不能使用